﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NngLevelEditor.Entities;
using Microsoft.Xna.Framework;
using NngLevelEditor.Manager;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;

namespace NngLevelEditor.Utility
{
    public class Level
    {
        private List<Entity> _entities;
        private TileGrid _grid;
        private Sprite _background;
        private int _bg;

        private String _path;

        #region Properties

        [CategoryAttribute("Level Strings"), DescriptionAttribute("The name of the level.")]
        public string LevelName
        {
            get;
            set;
        }

        [CategoryAttribute("Level Strings"), DescriptionAttribute("The description text of this level.")]
        public string LevelDescription
        {
            get;
            set;
        }

        [CategoryAttribute("Time"), DescriptionAttribute("The time to beat the level.")]
        public float Time
        {
            get;
            set;
        }

        public int Background
        {
            get { return _bg; }
            set
            {
                _bg = value;
                OnBackgroundChange();
            }
        }

        #endregion

        public Level()
        {
            _entities = new List<Entity>();
            _grid = new TileGrid();
            _path = null;
        }

        // to load a level
        public Level(string levelfile)
        {
            _entities = new List<Entity>();
            _grid = new TileGrid();
            _path = levelfile;
        }

        private void Initialize()
        {
            if (_path.Equals(""))
            {
                _background = new Sprite();
                _background.Position = Vector2.Zero; 
                _bg = 0;
            }
        }

        public void AddEntity(Entity e)
        {
            _entities.Add(e);
        }

        public void RemoveEntity(Entity e)
        {
            _entities.Remove(e);
            ((SpriteEntity)e).UnloadContent();
        }

        public void AddTile(Entity t)
        {
            try
            {
                _grid.Add((Tile)t);
            }
            catch
            {

            }
        }

        public void RemoveTile(Entity t)
        {
            try
            {
                _grid.Remove((Tile)t);
            }
            catch
            {

            }
        }

        /// <summary>
        /// Selects an entity in edit mode.
        /// </summary>
        /// <param name="clickPosition">the position of the click</param>
        /// <returns>The position of the Selected Entity</returns>
        public Vector2? SelectEntity(Vector2 clickPosition)
        {
            if (SelectionManager.SelectedEntity != null)
            {
                SelectionManager.SelectedEntity.Deselect();
            }
            Vector2 selectionSize = new Vector2(32.0f, 32.0f);
            selectionSize = selectionSize.ToWorldUnits();
            try
            {
                if (!_grid.DetectSelection(clickPosition))
                {
                    foreach (Entity e in _entities)
                    {
                        Vector2 deltaPosition = e.Position - clickPosition;
                        if (Math.Abs(deltaPosition.X) < (selectionSize.X) && Math.Abs(deltaPosition.Y) < (selectionSize.X))
                        {
                            SelectionManager.SelectedEntity = e;
                            e.Select();
                            return e.Position;
                        }
                    }
                }
                else
                {
                    return SelectionManager.SelectedEntity.Position;
                }
                //SelectionManager.SelectedEntity = null;
            }
            catch
            {
                SelectionManager.SelectedEntity.Deselect();
                SelectionManager.SelectedEntity = null;
            }

            return null;
        }

        protected void Clear()
        {
            try
            {
                foreach (Entity e in _entities)
                {
                    ((SpriteEntity)e).UnloadContent();
                }

                _entities.Clear();

                _grid.Clear();
                _background.UnloadContent();
            }
            catch
            {

            }
        }

        private void OnBackgroundChange()
        {
            if (_background != null)
            {
                GraphicsManager.RemoveSprite(_background);
            }

            try
            {
                _background = GraphicsManager.AddSprite("bg/" + _bg, "Content", GraphicsManager.Layer.Background);
                _background.Position = Vector2.Zero;
            }
            catch
            {
                _background = new Sprite();
            }
            
        }

        public string CreateSaveString()
        {
            string saveString = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
                              + "<XnaContent>\n"
                              + _grid.GetFileString()
                              + _entities.GetFileString(_grid.MinTileX, _grid.MinTileY)
                              + "</XnaContent>\n";

            return saveString;
        }

        public void SetPath(string path)
        {
            _path = path;
        }

        public string GetPath()
        {
            return _path;
        }

        public void Save()
        {
            if (_path.Length > 0)
            {
                try
                {
                    StreamWriter write = new StreamWriter(_path, false);
                    write.WriteLine(CreateSaveString());
                    write.Close();

                    MessageBox.Show(_path + " saved successfully!");
                }
                catch
                {
                    MessageBox.Show("Save Unsuccessful!");
                }
            }

        }

        public void Open()
        {
            if (_path.Length > 0)
            {
                this.Clear();

                StreamReader read = new StreamReader(_path, false);
                List<Entity> go = new List<Entity>();
                TileGrid t = new TileGrid();
                while (!read.EndOfStream)
                {
                    string[] line = read.ReadLine().Split(' ');
                    if (line[0].Equals("bg"))
                    {
                        Background = int.Parse(line[1]);
                    }
                    else if (line[0].Equals("n"))
                    {
                        t.Add(new Tile(line));
                    }
                    else if (line[0].Equals("b"))
                    {
                        // change the last ones to line[1], line[2] to load brandon's levels.
                        go.Add(new NngLevelEditor.Entities.Button(line));
                    }
                    else if (line[0].Equals("v"))
                    {
                        go.Add(new Velcro(line));
                    }
                    else if (line[0].Equals("o"))
                    {
                        go.Add(new TwoPointEntity(line));
                    }
                    else if (line[0].Equals("k"))
                    {
                        go.Add(new Buckle(line));
                    }
                    else if (line[0].Equals("ln"))
                    {
                        LevelName = "";
                        for (int i = 1; i < line.Length; i++)
                        {
                            LevelName += line[i] + " ";
                        }
                        LevelName.Trim();
                    }
                    else if (line[0].Equals("ld"))
                    {
                        LevelDescription = "";
                        for (int i = 1; i < line.Length; i++)
                        {
                            LevelDescription += line[i] + " ";
                        }
                        LevelDescription.Trim();
                    }
                }

                _entities = go;
                _grid = t;

                read.Close();

            }
        }

        public void New()
        {
            Clear();

            _path = "";
        }
    }
}
